package com.snap.vseries.pdf;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.print.PrintManager;
import android.util.SparseArray;

import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.FontFactory;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfPTableEvent;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.draw.LineSeparator;
import com.snap.vseries.AppConfig;
import com.snap.vseries.Constants;
import com.snap.vseries.bean.ChannelBean;
import com.snap.vseries.bean.ExpInfo;
import com.snap.vseries.utils.AutoUtil;
import com.snap.vseries.utils.FileUtils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;

public class PdfManager {
    private static final String MODEL = "V10 Real-time PCR System";
    private static final int DISABLE_BORDER_SIDE_NO = 0x01;
    private static final int DISABLE_BORDER_SIDE_LEFT = 0x02;
    private static final int DISABLE_BORDER_SIDE_RIGHT = 0x03;
    private static final int DISABLE_BORDER_SIDE_ALL = 0x04;
    /**
     * 最大宽度
     */
    private static final float maxWidth = PageSize.A4.getWidth() - 46 * 2;
    private static final Object OBJECT = new Object();
    private static PdfManager instance;
    final String encoding = Constants.NormalEncoding;//BaseFont.IDENTITY_H;
    String fontName = Constants.NormalFont;
    private ExpInfo experimentInfo;

    public synchronized static PdfManager get() {
        if (instance == null) {
            synchronized (OBJECT) {
                if (null == instance) {
                    instance = new PdfManager();
                }
            }
        }
        return instance;
    }

    /**
     * 图例
     *
     * @return
     */
    private static Bitmap createSample() {
        Bitmap bitmap = Bitmap.createBitmap(900, 80, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        canvas.drawColor(0xFFFFFFFF);

        Paint fontPaint = new Paint();
        fontPaint.setAntiAlias(true);
        fontPaint.setStyle(Paint.Style.FILL);
        fontPaint.setColor(0xFF509CF9);
        fontPaint.setTextSize(38);
        fontPaint.setColor(0xFF666666);
        fontPaint.setStrokeWidth(1);

        Paint rectPaint = new Paint();
        rectPaint.setAntiAlias(true);
        rectPaint.setStyle(Paint.Style.FILL);

        float rectWidth = 48;
        float rectHeight = 14;
        float rectMarginLeft = 80;
        float rectMarginRight = 20;
        float rectY = 80 / 2f - rectHeight / 2f;

        rectPaint.setColor(0xFF509CF9);
        float xRight = 0;
        canvas.drawRoundRect(new RectF(xRight, rectY, xRight + rectWidth, rectY + rectHeight), 10, 10, rectPaint);
        String tip = "FAM";
        Rect rect1 = new Rect();
        fontPaint.getTextBounds(tip, 0, tip.length(), rect1);
        xRight += rectWidth + rectMarginRight;
        canvas.drawText(tip, xRight, 80 / 2f + rect1.height() / 2f, fontPaint);

        rectPaint.setColor(0xFF63C03A);
        xRight += rectMarginLeft + rect1.width();
        canvas.drawRoundRect(new RectF(xRight, rectY, xRight + rectWidth, rectY + rectHeight), 10, 10, rectPaint);
        tip = "VIC";
        Rect rect2 = new Rect();
        xRight += rectWidth + rectMarginRight;
        fontPaint.getTextBounds(tip, 0, tip.length(), rect2);
        canvas.drawText(tip, xRight, 80 / 2f + rect2.height() / 2f, fontPaint);


        rectPaint.setColor(0xFFFFD40C);
        xRight += rectMarginLeft + rect2.width();
        canvas.drawRoundRect(new RectF(xRight, rectY, xRight + rectWidth, rectY + rectHeight), 10, 10, rectPaint);
        tip = "ROX";
        Rect rect3 = new Rect();
        xRight += rectWidth + rectMarginRight;
        fontPaint.getTextBounds(tip, 0, tip.length(), rect3);
        canvas.drawText(tip, xRight, 80 / 2f + rect3.height() / 2f, fontPaint);

        rectPaint.setColor(0xFFF95050);
        xRight += rectMarginLeft + rect3.width();
        canvas.drawRoundRect(new RectF(xRight, rectY, xRight + rectWidth, rectY + rectHeight), 10, 10, rectPaint);
        tip = "CY5";
        xRight += rectWidth + rectMarginRight;
        fontPaint.getTextBounds(tip, 0, tip.length(), new Rect());
        canvas.drawText(tip, xRight, 80 / 2f + rect3.height() / 2f, fontPaint);
        canvas.save(Canvas.ALL_SAVE_FLAG);
        canvas.restore();
        return bitmap;
    }

    /**
     * 生成PDF
     *
     * @param context         上下文
     * @param ampOriginBitmap 标准曲线
     * @param ampFitBitmap    扩增曲线
     * @param path            pdf存放路径
     * @param experimentInfo  实验信息
     * @param isOpen          是否开启熔解
     * @return
     */
    public synchronized boolean makePdf(Context context, Bitmap ampOriginBitmap, Bitmap ampFitBitmap, String path, String generateTime, ExpInfo experimentInfo, boolean isOpen) {
        this.experimentInfo = experimentInfo;
        boolean result = false;
        if (experimentInfo.getHoleInfo() == null) {
            return false;
        }
        try {
            //595
            Document document = new Document(PageSize.A4);
            document.setMargins(46, 46, 108, 50);
//            path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + experimentInfo.getExperimentName() + ".pdf";
            path = path + "/" + String.format("%s", generateTime) + ".pdf";
            File file = new File(path);
            if (file.exists()) {
                file.delete();
            }
            PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
            writer.setPageEvent(new PdfHeaderAndFooterHelper(experimentInfo.getName()));
            document.open();

            //报告首页
            generatePDF1(document);
            //结果概要
            generatePDF2(document);
            //孔位信息
            generatePDF3(document);
            //荧光图谱
            if (isOpen) {
                generatePDF4(document, context, ampFitBitmap, "荧光图谱", true);
                //熔解图谱
                generatePDF4(document, context, ampOriginBitmap, "熔解图谱", false);
            } else {
                generatePDF4(document, context, ampOriginBitmap, "标准图谱", true);
                generatePDF4(document, context, ampFitBitmap, "扩增图谱", false);
            }
            document.close();
            FileUtils.ensureWriteFile(file);
            result = true;
//            doPdfPrint(file.getAbsolutePath());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 调用打印服务
     *
     * @param filePath PDF文件所在路径
     */
    private void doPdfPrint(String filePath, Context context) {
        String jobName = "实验报告" + experimentInfo.getName() + ".pdf";
        PrintManager printManager = (PrintManager) context.getSystemService(Context.PRINT_SERVICE);
        PrintPdfAdapter myPrintAdapter = new PrintPdfAdapter(filePath);
        printManager.print(jobName, myPrintAdapter, null);
    }

    /**
     * 报告首页
     */
    private void generatePDF1(Document document) throws Exception {
        Font font12_gray = FontFactory.getFont(fontName, encoding, BaseFont.EMBEDDED, 12, Font.NORMAL);
        font12_gray.setColor(BaseColor.GRAY);
        Font font12_black = FontFactory.getFont(fontName, encoding, BaseFont.EMBEDDED, 12, Font.NORMAL);
        font12_black.setColor(BaseColor.BLACK);
        Font font16_gray = FontFactory.getFont(fontName, encoding, BaseFont.EMBEDDED, 16, Font.NORMAL);
        font16_gray.setColor(BaseColor.GRAY);
        Font font28_black_bold = FontFactory.getFont(fontName, encoding, BaseFont.EMBEDDED, 28, Font.BOLD);
        PdfPTable table1 = createTable(new float[]{PageSize.A4.getWidth()});
        table1.addCell(createCellNoBorder("实验结果报告", font16_gray, 30, 18));
        table1.addCell(createCellNoBorder(experimentInfo.getName(), font28_black_bold, 18, 18));
        Paragraph p1 = new Paragraph();
        LineSeparator lineSeparator = new LineSeparator(1, 16, BaseColor.GRAY, Element.ALIGN_LEFT, 0);
        p1.add(lineSeparator);
        p1.setIndentationLeft(18);
        p1.setSpacingBefore(46f);
        p1.setSpacingAfter(96f);
        PdfPTable table2 = createTable(new float[]{50, 200});
        String startTime = new SimpleDateFormat("yyyy/MM/dd HH:mm").format(experimentInfo.getStartTime());
        String endTime = new SimpleDateFormat("HH:mm").format(experimentInfo.getEndTime());

//        table2.addCell(createCell("检测项目", font12_black, 25, 0, 18));
//        table2.addCell(createCell(experimentInfo.getTemplateInfo().getExperimentName(), font12_black, 25, 0, 0));
        //paddingLeft,64-46
        table2.addCell(createCellNoBorder("文件名称", font12_black, 25, 0, 18));
        table2.addCell(createCellNoBorder(experimentInfo.getName() + ".exp", font12_black, 25, 0, 0));
        table2.addCell(createCellNoBorder("实验时间", font12_black, 25, 0, 18));
        table2.addCell(createCellNoBorder(startTime + " - " + endTime, font12_black, 25, 0, 0));
        table2.addCell(createCellNoBorder("运行时长", font12_black, 25, 0, 18));
        table2.addCell(createCellNoBorder(AutoUtil.getHourAndMin((experimentInfo.getEndTime() - experimentInfo.getStartTime()) / 1000), font12_black, 25, 0, 0));
        table2.addCell(createCellNoBorder("实验人员", font12_black, 25, 0, 18));
        table2.addCell(createCellNoBorder("Public", font12_black, 25, 0, 0));
        table2.addCell(createCellNoBorder("仪器型号", font12_black, 25, 0, 18));
        table2.addCell(createCellNoBorder(MODEL, font12_black, 25, 0, 0));
        table2.addCell(createCellNoBorder("实验孔数", font12_black, 25, 0, 18));
        table2.addCell(createCellNoBorder(String.format("%02d", 1) + " / " + String.format("%02d", 1), font12_black, 25, 0, 0));
        table2.addCell(createCellNoBorder("报告孔数", font12_black, 25, 0, 18));
        table2.addCell(createCellNoBorder(String.format("%02d", 1) + "/ " + String.format("%02d", 1), font12_black, 25, 0, 0));
        Paragraph p2 = new Paragraph();
        p2.setFont(font12_black);
        p2.setAlignment(2);
        p2.add(new Chunk("实验人员：    "));
        p2.setFont(font12_gray);
        p2.add(new Chunk("                              ").setUnderline(1, Rectangle.BOTTOM));
        p2.setFont(font12_black);
        p2.add(new Chunk("            核验人员：    "));
        p2.setFont(font12_gray);
        p2.add(new Chunk("                              ").setUnderline(1, Rectangle.BOTTOM));
        p2.setIndentationLeft(18);
        p2.setSpacingBefore(120);
        document.add(table1);
        document.add(p1);
        document.add(table2);
        document.add(p2);
        document.newPage();
    }

    /**
     * 结果概要
     */
    private void generatePDF2(Document document) throws Exception {
        Font font18_black_bold = FontFactory.getFont(fontName, encoding, BaseFont.EMBEDDED, 18, Font.BOLD);
        Font font10_black = FontFactory.getFont(fontName, encoding, BaseFont.EMBEDDED, 10, Font.NORMAL);
        Font font10_black_bold = FontFactory.getFont(fontName, encoding, BaseFont.EMBEDDED, 10, Font.BOLD);

        PdfPTable table = createTable(new float[]{50, 116, 50, 116, 116});
        table.addCell(createCellTitle("结果概要", font18_black_bold, 6));
        table.addCell(createCell("孔位", font10_black_bold, Element.ALIGN_CENTER, DISABLE_BORDER_SIDE_LEFT));
        table.addCell(createCell("样本名称", font10_black_bold, Element.ALIGN_CENTER, DISABLE_BORDER_SIDE_NO));
        table.addCell(createCell("通道", font10_black_bold, Element.ALIGN_CENTER, DISABLE_BORDER_SIDE_NO));
        table.addCell(createCell("探针染料", font10_black_bold, Element.ALIGN_CENTER, DISABLE_BORDER_SIDE_NO));
        table.addCell(createCell("CT值", font10_black_bold, Element.ALIGN_CENTER, DISABLE_BORDER_SIDE_RIGHT));
        SparseArray<ChannelBean> channelData = experimentInfo.getHoleInfo().getChannelData();
        for (int i = 0; i < channelData.size(); i++) {
            int position = i;
            ChannelBean bean = channelData.valueAt(position);
            int channelIndex = channelData.keyAt(position) / AppConfig.TOTAL_HOLE_COUNT;
            float ct = bean.getCtValue();
            String holeName = String.format("%02d", i + 1);
            table.addCell(createCell(holeName, font10_black, DISABLE_BORDER_SIDE_LEFT));
            table.addCell(createCell(experimentInfo.getSampleName() == null ? "N/A" : experimentInfo.getSampleName(), font10_black, DISABLE_BORDER_SIDE_NO));
            table.addCell(createCell(AppConfig.CHANNEL_NAMES[channelIndex].toUpperCase(), font10_black, DISABLE_BORDER_SIDE_NO));
            table.addCell(createCell("N/A", font10_black, DISABLE_BORDER_SIDE_NO));
            table.addCell(createCell(ct == 0f ? "-" : String.valueOf(ct), font10_black, DISABLE_BORDER_SIDE_RIGHT));
        }
        PdfPTableEvent event = new AlternatingBackground();
        table.setTableEvent(event);
        document.add(table);
        document.newPage();
    }

    /**
     * 孔位信息
     */
    private void generatePDF3(Document document) throws Exception {
        Font font18_black_bold = FontFactory.getFont(fontName, encoding, BaseFont.EMBEDDED, 18, Font.BOLD);
        Chunk title = new Chunk("孔位信息", font18_black_bold);
        PdfPTable table;
        table = createTable(new float[]{106});
        table.setTotalWidth(212);
        table.setHorizontalAlignment(Element.ALIGN_LEFT);
        table.setSpacingBefore(50);
        table.addCell(createCell());
        document.add(title);
        document.add(table);
        document.newPage();
    }

    /**
     * 荧光图谱
     */
    private void generatePDF4(Document document, Context context, Bitmap bitmap, String titleContent, boolean newPage) throws Exception {
        Font font18_black_bold = FontFactory.getFont(fontName, encoding, BaseFont.EMBEDDED, 18, Font.BOLD);

        Paragraph title = new Paragraph(titleContent, font18_black_bold);

        document.add(title);

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        final Bitmap sample = createSample();
        sample.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
        Image image = Image.getInstance(outputStream.toByteArray());
        image.setAbsolutePosition(47, 600);
        image.scaleAbsolute(252, 20);
        document.add(image);
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        if (bitmap == null) {
            return;
        }
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
        Image image1 = Image.getInstance(stream.toByteArray());
        image1.setAbsolutePosition(47, 150);
        image1.scaleAbsolute(505, 434);
        document.add(image1);
        if (newPage) {
            document.newPage();
        }
    }

    private PdfPCell createCell() {
        Font font9_black = FontFactory.getFont(fontName, encoding, BaseFont.EMBEDDED, 9, Font.NORMAL);
        Font font12_gray_bold = FontFactory.getFont(fontName, encoding, BaseFont.EMBEDDED, 12, Font.BOLD);
        font12_gray_bold.setColor(new BaseColor(192, 192, 192));
        Font font9_white_bold = FontFactory.getFont(fontName, encoding, BaseFont.EMBEDDED, 9, Font.BOLD);
        font9_white_bold.setColor(BaseColor.WHITE);

        Phrase content = new Phrase(500);

        content.setFont(font9_black);
        content.add(new Chunk(Chunk.NEWLINE));
        content.add(new Chunk(Chunk.NEWLINE));
        if (experimentInfo.getHoleInfo().isFamEnable()) {
            //FAM-1080p
            content.add(new Chunk("FAM"));
            content.add(new Chunk(Chunk.NEWLINE));
            content.add(new Chunk(Chunk.NEWLINE));
        }
        if (experimentInfo.getHoleInfo().isVicEnable()) {
            content.add(new Chunk("VIC"));
            content.add(new Chunk(Chunk.NEWLINE));
            content.add(new Chunk(Chunk.NEWLINE));
        }
        if (experimentInfo.getHoleInfo().isRoxEnable()) {
            //ROX-N/A
            content.add(new Chunk("ROX"));
            content.add(new Chunk(Chunk.NEWLINE));
            content.add(new Chunk(Chunk.NEWLINE));
        }
        if (experimentInfo.getHoleInfo().isCy5Enable()) {
            content.add(new Chunk("CY5"));
        }


        PdfPCell cell = new PdfPCell();
        cell.setMinimumHeight(70);
        cell.setPhrase(content);
        cell.setPaddingBottom(10.0f);
        cell.setPaddingTop(10.0f);
        cell.setPaddingLeft(10.0f);
        cell.setPaddingRight(10f);
        cell.setBorderWidth(1);
        cell.setBorderColor(new BaseColor(192, 192, 192));
        return cell;
    }

    private PdfPCell createCellTitle(String value, Font font, int colspan) {
        PdfPCell cell = createCell(value, font, 0, 54, 0, 0, DISABLE_BORDER_SIDE_ALL);
        cell.setColspan(colspan);
        return cell;
    }

    private PdfPCell createCellNoBorder(String value, Font font, float paddingTop, float paddingLeft) {
        return createCell(value, font, paddingTop, 0, paddingLeft, 0, DISABLE_BORDER_SIDE_ALL);
    }

    //createCellNoBorder("文件名称", font12_black, 25, 0, 18)
    private PdfPCell createCellNoBorder(String value, Font font, float paddingTop, int paddingBottom, float paddingLeft) {
        return createCell(value, font, paddingTop, paddingBottom, paddingLeft, 0, DISABLE_BORDER_SIDE_ALL);
    }

    private PdfPCell createCell(String value, Font font, int disableBorderSide) {
        PdfPCell cell = createCell(value, font, 12, 12, 0, 0, disableBorderSide);
        cell.setBorderColor(new BaseColor(209, 209, 209));
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        return cell;
    }

    private PdfPCell createCell(String value, Font font, int align, int disableBorderSide) {
        PdfPCell cell = createCell(value, font, disableBorderSide);
        cell.setHorizontalAlignment(align);
        cell.setBorderColorTop(BaseColor.BLACK);
        cell.setBorderWidthTop(3);
        return cell;
    }

    /**
     * @param disableBorderSide 隐藏哪条边
     *                          DISABLE_BORDER_SIDE_LEFT 隐藏左边
     *                          DISABLE_BORDER_SIDE_RIGHT 隐藏右边
     *                          DISABLE_BORDER_SIDE_NO 不隐藏
     *                          DISABLE_BORDER_SIDE_ALL 全部隐藏
     */
    private PdfPCell createCell(String value, Font font, float paddingTop, float paddingBottom, float paddingLeft, float paddingRight, int disableBorderSide) {
        PdfPCell cell = new PdfPCell();
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setHorizontalAlignment(Element.ALIGN_LEFT);
        cell.setPhrase(new Phrase(value, font));

        if (disableBorderSide == DISABLE_BORDER_SIDE_LEFT) {
            cell.setBorder(Rectangle.BOTTOM | Rectangle.TOP | Rectangle.RIGHT);
        } else if (disableBorderSide == DISABLE_BORDER_SIDE_RIGHT) {
            cell.setBorder(Rectangle.BOTTOM | Rectangle.TOP | Rectangle.LEFT);
        } else if (disableBorderSide == DISABLE_BORDER_SIDE_ALL) {
            cell.setBorder(0);
        } else {
            cell.setBorder(Rectangle.BOTTOM | Rectangle.TOP | Rectangle.LEFT | Rectangle.RIGHT);
        }
        cell.setPaddingTop(paddingTop);
        cell.setPaddingBottom(paddingBottom);
        cell.setPaddingLeft(paddingLeft);
        cell.setPaddingRight(paddingRight);
        return cell;
    }

    /**
     * 创建指定列宽、列数的表格
     *
     * @param widths 各列宽度
     * @return 表格
     */
    private PdfPTable createTable(float[] widths) {
        PdfPTable table = new PdfPTable(widths);
        try {
            table.setTotalWidth(maxWidth);
            table.setLockedWidth(true);
            table.setHorizontalAlignment(Element.ALIGN_CENTER);
            table.getDefaultCell().setBorder(1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return table;
    }
}
